#include <string>
#include "LogicService.h"
#include "Server/LogicServiceFactory.h"
#include "base/core/lua_parser.h"
#include "base/core/os/debug.h"
#include "base/core/Profiler.h"
#include "base/core/random.h"
#include "base/core/log.h"
#include "Common/Utility/ServiceUtility.h"
#include "Common/Utility/ServerTime.h"
#include "Common/Utility/TimeUtility.h"
#include "Common/NetPack/NetPack.h"
#include "ProtoBuffer/AllProtocol.h"
#include "Access/CharacterDataSet.h"
#include "Script/ScriptMgr.h"
#include "Scene/MapMgr.h"
#include "Skill/SkillMgr.h"
#include "Character/PlayerMgr.h"
#include "Character/monster/MonsterMgr.h"
#include "Item/ItemUseMgr.h"
#include "Mission/MissionManager.h"
#include "Character/monster/MonsterRefMgr.h"
#include "Character/monster/MonsterRefCfg.h"
#include "Character/npc/NpcMgr.h"
#include "Duplicate/DuplicateMgr.h"
#include "Character/drop/DropMgr.h"
#include "Character/buff/BuffEffectCfg.h"
#include "Character/buff/BuffEffectInfo.h"
#include "Character/buff/BuffEffectLogicManager.h"

#include "ServerModule/LogicServerModuleMgr.h"
#include "Mail/GMailManager.h"
#include "Mall/GMallManager.h"
#include "Achievement/AchievementMgr.h"
#include "Character/object/ObjectMgr.h"
#include "Character/newAI/behaviac/BehaviacAIManager.h"
#include "Character/CreatureMgr.h"
#include "Team/GTeamManager.h"

#include "Auctioneer/AuctioneerMgr.h"
#include "Global/LGlobalMgr.h"
#include "Effect/EffectMgr.h"
#include "GM/GmMgr.h"
#include "Treasure/TreasureMgr.h"
#include "GArena/GArenaMgr.h"
#include "Rebot/RebotMgr.h"
#include "Answer/AnswerMgr.h"
#include "GQueryMgr/GQueryMgr.h"
#include "ServerModule/LogicActivityModule.h"
#include "ServerModule/LogicEscortModule.h"
#include "PlaneMgr/PlaneMgr.h"
#include "Common/ErrCollect/ErrCollect.h"
#include "Chat/ChatManager.h"
#include "Character/welfare/OperateWelfareMgr.h"
#include "PayLogicMgr/PayLogicMgr.h"
#include "Notify/LNotifyMgr.h"
#include "Adventure/AdventureMgr.h"

//#pragma warning(disable:4189)
//#pragma warning(disable:4244)
//#pragma warning(disable:4100)

using namespace std;

namespace
{
	static const char s_config_file[] = "./config.lua";
	static const char s_LogicMap_file[] = "../LogicMap.lua";
	static const char s_LogicMap_BackUp_file[] = "./LogicMap.lua";
}

Service*  MakeLogicService()
{
	return LogicService::Instance();
}

void  DeleteLogicService(Service* service)
{
	_UNUSE(service);
	LogicService::Destroy();
}

LogicService::LogicService()
	: Service(LOGIC_SERVER)
	//, m_groupId(0)
	//, m_listenHandle(nullptr)
	, m_outerPort(0)
	, m_startMark(0)
	, m_connectFlag(0)
	, m_lastDayChangeTime(0)
	, m_syncStateTick(0)
	, m_dbRequestCount(0)
	, m_pMessageDispatch(nullptr)
	, m_logServer()
	, m_dbproxyServer()
	, m_centerServer()
	//, m_firstConnectCenter(true)
{
	memset(m_listenIP, 0, sizeof(m_listenIP));
	memset(m_outerIP, 0, sizeof(m_outerIP));
}

LogicService::~LogicService()
{
}

bool LogicService::Init(Net* net, const char* configFile)
{
	bool result = false;
//	bool retCode = false;
	LuaScript* script = nullptr;
	uint64_t curTime = 0;
	MMOLOG_ASSERT_EXIT(net != NULL);
	m_net = net;

	m_startMark = MMO_MAKELONGLONG(Random(), Random());

	//消息分发
	m_pMessageDispatch = new MessageDispatch(this);
	MMOLOG_PROCESS_ERROR(m_pMessageDispatch);

	if (!_LoadConfig(configFile))
	{
		LogErrFmtPrint("[logic] load config %s fail", configFile);
		goto Exit0;
	}

	//放在前面计算,可能后面管理器初始化的时候要用到,放到 _LoadConfig 之后
	curTime = g_GetGlobalServerTime()->UnixSec();
	_CalcWeekCountFromOpen(curTime);

	MMOLOG_PROCESS_ERROR(g_MakeLogicServerModuleMgr());
	if (!g_GetLogicServerModuleMgr()->Init())
	{
		LogErrPrint("[logic] g_GetLogicServerModuleMgr InitBehavic fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeCreatureMgr());
	if (!g_GetCreatureMgr()->Init())
	{
		LogErrPrint("[logic] creature mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeBehaviacAIMgr());
	if (!g_GetBehaviacAIMgr()->Init())
	{
		LogErrPrint("[logic] g_GetBehaviacAIMgr InitBehavic fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeBuffBagEffectCfgMgr());
	if (!g_GetBuffBagEffectCfgMgr()->Init())
	{
		LogErrPrint("[logic] buff bag effect cfg mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeBuffLogicManager());
	if (!g_GetBuffLogicManager()->Init())
	{
		LogErrPrint("[logic] buff logic mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeScriptMgr());
	if (!g_GetScriptMgr()->Init()) 
	{
		LogErrPrint("[logic] script mgr init fail");
		goto Exit0;
	}
	
	MMOLOG_PROCESS_ERROR(g_MakeSkillMgr());
	if (!g_GetSkillMgr()->Init())
	{
		LogErrPrint("[logic] skill mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeItemUseMgr());
	if (!g_GetItemUseMgr()->Init())
	{
		LogErrPrint("[logic] itemuse mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeDropMgr());
	if (!g_GetDropMgr()->Init())
	{
		LogErrPrint("[logic] drop mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeOperateWelfareMgr());
	if (!g_GetOperateWelfareMgr()->Init())
	{
		LogErrPrint("[logic] operate welfare mgr init fail");
		goto Exit0;
	}

	//采集物件
	MMOLOG_PROCESS_ERROR(g_MakeObjectMgr());
	if (!g_GetObjectMgr()->Init())
	{
		LogErrPrint("[logic] object mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakePlayerMgr());
	if (!g_GetPlayerMgr()->Init()) 
	{
		LogErrPrint("[logic] player mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeMonsterMgr());
	if (!g_GetMonsterMgr()->Init())
	{
		LogErrPrint("[logic] monster mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeNpcMgr());
	if (!g_GetNpcMgr()->Init())
	{
		LogErrPrint("[logic] npc mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeCharacterDataSet());
	if (!g_GetCharacterDataSet()->Init())
	{
		LogErrPrint("[logic] character data set mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeMapMgr());
	if (!g_GetMapMgr()->Init())
	{
		LogErrPrint("[logic] map mgr init fail");
		goto Exit0;
	}
	
	//任务要放到 g_GetMapMgr 后面初始化，任务初始化用到了地编里的生物
	MMOLOG_PROCESS_ERROR(g_MakeMissionManager());
	if (!g_GetMissionManager()->Init())
	{
		LogErrPrint("[logic] mission mgr init fail");
		goto Exit0;
	}

	//副本 副本要放到 g_GetMissionManager 之后初始化，新手副本脚本中配置了任务ID
	MMOLOG_PROCESS_ERROR(g_MakeDuplicateMgr());
	if (!g_GetDuplicateMgr()->Init())
	{
		LogErrPrint("[logic] duplicate mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeGMailMgr());
	if (!g_GetGMailMgr()->Init())
	{
		LogErrPrint("[logic] gmail mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeGMallMgr());
	if (!g_MakeGMallMgr()->Init())
	{
		LogErrPrint("[logic] gmall mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeAchievementMgr());
	if (!g_GetAchievementMgr()->Init())
	{
		LogErrPrint("[logic] Achievement mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeGTeamMgr());
	if (!g_GetGTeamMgr()->Init())	{
		LogErrPrint("[logic] TeamManager mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeLGlobalMgr());
	if (!g_GetLGlobalMgr()->Init())
	{
		LogErrPrint("[logic] LGobalMgr mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeAuctioneerMgr());
	if (!g_GetAuctioneerMgr()->Init())
	{
		LogErrPrint("[logic] Auctioneer mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeEffectMgr());
	if (!g_GetEffectMgr()->Init())
	{
		LogErrPrint("[logic] Effect mgr init fail");
		goto Exit0;
	}	

	MMOLOG_PROCESS_ERROR(g_MakeGmMgr());
	if (!g_GetGmMgr()->Init())
	{
		LogErrPrint("[logic] Gm mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeTreasureMgr());
	if (!g_GetTreasureMgr()->Init())
	{
		LogErrPrint("[logic] Treasure mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeGArenaMgr());
	if (!g_GetGArenaMgr()->Init())
	{
		LogErrPrint("[logic] GArena mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeRebotMgr());
	if (!g_GetRebotMgr()->Init())
	{
		LogErrPrint("[logic] rebot mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeAnswerMgr());
	if (!g_GetAnswerMgr()->Init())
	{
		LogErrPrint("[logic] answer mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeGQueryMgr());
	if (!g_GetGQueryMgr()->Init())
	{
		LogErrPrint("[logic] Gquery mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeGActivityMgr());
	if (!g_GetGActivityMgr()->Init())
	{
		LogErrPrint("[logic] activity mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeGEscortMgr());
	if (!g_GetGEscortMgr()->Init())
	{
		LogErrPrint("[logic] escort mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakePlaneMgr());
	if (!g_GetPlaneMgr()->Init())
	{
		LogErrPrint("[logic] plane mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeChatMgr());
	if (!g_GetChatMgr()->Init())
	{
		LogErrPrint("[logic] chat mgr init fail");
		goto Exit0;
	}
	MMOLOG_PROCESS_ERROR(g_MakePayLogicMgr());
	if (!g_GetPayLogicMgr()->Init())
	{
		LogErrPrint("[logic] pay mgr init fail");
		goto Exit0;
	}
	MMOLOG_PROCESS_ERROR(g_MakeLNotifyMgr());
	if (!g_GetLNotifyMgr()->Init())
	{
		LogErrPrint("[logic] LNotify mgr init fail");
		goto Exit0;
	}
	//一定要放到  g_GetMissionManager  后面，解析条件的时候用到了  g_GetMissionManager 里面的接口
	MMOLOG_PROCESS_ERROR(g_MakeAdventureMgr());
	if (!g_GetAdventureMgr()->Init())
	{
		LogErrPrint("[logic] adventure mgr init fail");
		goto Exit0;
	}

//	retCode = _ListenAddress();
//	MMOLOG_PROCESS_ERROR(retCode);

	m_lastDayChangeTime = ServerTime::UnixSec();

	script = g_GetScriptMgr()->GetScript();
	if (script)
	{
		//@temp by JinnMa
//		script->CallTableFuncVoid("LSEvent", "OnStart");
	}

	SetRuningStatus(STATUS_RUNNING);

	snprintf(m_srvTotalName, SERVER_NAME, "zone%d_logic%d", m_zid, m_id);
	LogInfoFmtPrint("%s started ......", m_srvTotalName);

	result = true;
Exit0:
	if (!result) 
	{
		UnInit();
	}
	return result;
}

bool LogicService::_LoadConfig(const char* config_file)
{
	bool result = false;
	bool retCode = false;
	LuaParser  parser;

	MMOLOG_ASSERT_EXIT(config_file);
	MMOLOG_PROCESS_ERROR(parser.OpenFile(config_file));

	{
		LuaRef  logic = parser.GetRef("Logic");
		MMOLOG_PROCESS_ERROR(logic.isTable());
		LuaRef  connect = logic["ConnectServers"];
		MMOLOG_PROCESS_ERROR(connect.isTable());

		retCode = LoadConfigConnectMap2Service(connect, "Gate", m_gateConnectMap);
		MMOLOG_PROCESS_ERROR(retCode);

		retCode = LoadConfigConnect2Service(connect, "Log", &m_logServer);
		MMOLOG_PROCESS_ERROR(retCode);
		m_logServer.connectState = CONNECT_STATE_READY;

		retCode = LoadConfigConnect2Service(connect, "CharDB", &m_dbproxyServer);
		MMOLOG_PROCESS_ERROR(retCode);
		m_dbproxyServer.connectState = CONNECT_STATE_READY;

		retCode = LoadConfigConnect2Service(connect, "Center", &m_centerServer);
		MMOLOG_PROCESS_ERROR(retCode);
		m_centerServer.connectState = CONNECT_STATE_READY;

		retCode = GetLuaTableValue(logic, "ID", &m_id);
		MMOLOG_PROCESS_ERROR(retCode);

		retCode = GetLuaTableValue(logic, "IP", m_listenIP, countof(m_listenIP));
		MMOLOG_PROCESS_ERROR(retCode);

		retCode = GetLuaTableValue(logic, "Port", &m_outerPort);
		MMOLOG_PROCESS_ERROR(retCode);
#ifdef WIN32
		double tmpTime=0;
		retCode = GetLuaTableValue(logic, "OpenTime", &tmpTime);
		m_openTime = (uint64_t)tmpTime;
		MMOLOG_PROCESS_ERROR(retCode);
#else
		retCode = GetLuaTableValue(logic, "OpenTime", &m_openTime);
		MMOLOG_PROCESS_ERROR(retCode);
#endif
		

		retCode = GetLuaTableValue(logic, "Zid", &m_zid);
		MMOLOG_ASSERT_EXIT(retCode);
	    MMOLOG_ASSERT_EXIT((m_zid > 0) && (m_zid < MAX_GROUP_ID));

		retCode = GetLuaTableValue(logic, "LoadAllMapIds", &m_loadAllMapIds);
		MMOLOG_PROCESS_ERROR(retCode);
	}
	result = true;
Exit0:
	return result;
}

bool LogicService::_OnCloseServer(ISession* session, void* context, CloseFlag flag) 
{
	bool               result = false;
	LogicService*       service = g_GetLogicService();
	ServiceConnectFlag connectFlag = CONNECT_FLAG_NULL;
	ServiceConnect*    serviceConnect = NULL;
	std::string        sessionName = "unknown";
	ServiceType        serviceType = SERVER_TYPE_NULL;
	SESSION_USER_DATA  userData;

	MMOLOG_ASSERT_EXIT(service != NULL);
	MMOLOG_ASSERT_EXIT(session != NULL);
	MMOLOG_ASSERT_EXIT(context != NULL);

	serviceConnect = (ServiceConnect*)context;
	userData = session->GetUserData();
	serviceType = (ServiceType)session->GetMark();

	switch (serviceType) 
	{
	case GATE_SERVER:
		connectFlag = CONNECT_GATE_SERVER;
		break;
	case DBPROXY_SERVER:
		connectFlag = CONNECT_DBPROXY_SERVER;
		break;
	case LOG_SERVER:
		connectFlag = CONNECT_LOG_SERVER;
		break;
	case CENTER_SERVER:
		connectFlag = CONNECT_CENTER_SERVER;
		break;
	default:
		MMO_ASSERT(false);
		goto Exit0;
		break;
	}

	MMOLOG_ASSERT_EXIT(serviceConnect != NULL);

	if (serviceType > SERVER_TYPE_NULL && serviceType < SERVICE_COUNT)
	{
		sessionName = s_service_name[serviceType];
	}
	else if (serviceType > WEB_SERVER_TYPE_NULL && serviceType < WEB_SERVICE_COUNT)
	{
		sessionName = s_web_service_name[serviceType % 100];
	}

	LogInfoFmtPrint("[logic] %s(id:%u,ip:%s) closed(%d)",
					sessionName.c_str(),
					serviceConnect->id,
					session->GetRemoteAddress().IPAndPort,
					flag
					);

	serviceConnect->session = nullptr;
	serviceConnect->connectState = CONNECT_STATE_READY;
	serviceConnect->serviceState = SERVICE_STATE_ERROR;
	service->_SetConnectFlag(connectFlag, false);

	result = true;
Exit0:
	return result;
}

void  LogicService::UnInit()
{
	if (g_GetMapMgr()) 
	{
		g_GetMapMgr()->UnInit();        
		g_DelMapMgr();
	}

	if (g_GetCharacterDataSet())
	{
		g_GetCharacterDataSet()->UnInit();
		g_DelCharacterDataSet();
	}
	//副本管理器释放必须要在场景之前（引用了场景）
	if (g_GetDuplicateMgr())
	{
		g_GetDuplicateMgr()->UnInit();
		g_DelDuplicateMgr();
	}

	if (g_GetObjectMgr())
	{
		g_GetObjectMgr()->UnInit();
		g_DelObjectMgr();
	}

	//掉落物品管理,一定要放在 g_GetItemMgr()和 g_GetSceneMgr 之前（引用了物品，和离开场景）
	if (g_GetDropMgr())
	{
		g_GetDropMgr()->UnInit();
		g_DelDropMgr();
	}

	if (g_GetMonsterMgr())
	{
		g_GetMonsterMgr()->UnInit();
		g_DelMonsterMgr();
	}

	if (g_GetOperateWelfareMgr())
	{
		g_GetOperateWelfareMgr()->UnInit();
		g_DelOperateWelfareMgr();
	}

	if (g_GetRebotMgr())
	{
		g_GetRebotMgr()->UnInit();
		g_DelRebotMgr();
	}

	if (g_GetNpcMgr())
	{
		g_GetNpcMgr()->UnInit();
		g_DelNpcMgr();
	}

	if (g_GetPlayerMgr())
	{
		g_GetPlayerMgr()->UnInit();
		g_DelPlayerMgr();
	}

	if (g_GetScriptMgr())
	{
		g_GetScriptMgr()->UnInit();
		g_DelScriptMgr();
	}

	if (g_GetBuffBagEffectCfgMgr())
	{
		g_GetBuffBagEffectCfgMgr()->UnInit();
		g_DelBuffBagEffectCfgMgr();
	}

	if (g_GetBuffLogicManager())
	{
		g_GetBuffLogicManager()->UnInit();
		g_DelBuffLogicManager();
	}

	if (g_GetGMailMgr())
	{
		g_GetGMailMgr()->UnInit();
		g_DelGMailMgr();
	}

	if (g_GetGMallMgr())
	{
		g_GetGMallMgr()->UnInit();
		g_DelGMallMgr();
	}

	if (g_GetLogicServerModuleMgr())
	{
		g_GetLogicServerModuleMgr()->UnInit();
		g_DelLogicServerModuleMgr();
	}

	//活动管理器需要放到 场景管理器之前，活动uninit的时候需要 回收活动相关的 怪物,NPC等
	if (g_GetGActivityMgr())
	{
		g_GetGActivityMgr()->UnInit();
		g_DelGActivityMgr();
	}

	if (g_GetSceneMgr())
	{
		g_GetSceneMgr()->UnInit();
		g_DelSceneMgr();
	}
	//成就 uninit 要放到场景之后，场景 uninit时 会触发计算属性，属性改变会触发成就
	if (g_GetAchievementMgr())
	{
		g_GetAchievementMgr()->UnInit();
		g_DelAchievementMgr();
	}


	if (g_GetGTeamMgr())
	{
		g_GetGTeamMgr()->UnInit();
		g_DelGTeamMgr();
	}

	if (g_GetLGlobalMgr())
	{
		g_GetLGlobalMgr()->UnInit();
		g_DelLGlobalMgr();
	}

	if (g_GetAuctioneerMgr())
	{
		g_GetAuctioneerMgr()->UnInit();
		g_DelAuctioneerMgr();
	}

	if (g_GetEffectMgr())
	{
		g_GetEffectMgr()->UnInit();
		g_DelEffectMgr();
	}

	if (g_GetGmMgr())
	{
		g_GetGmMgr()->UnInit();
		g_DelGmMgr();
	}

	if (g_GetTreasureMgr())
	{
		g_GetTreasureMgr()->UnInit();
		g_DelTreasureMgr();
	}


	if (g_GetGArenaMgr())
	{
		g_GetGArenaMgr()->UnInit();
		g_DelGArenaMgr();
	}

	if (g_GetAnswerMgr())
	{
		g_GetAnswerMgr()->UnInit();
		g_DelAnswerMgr();
	}

	if (g_GetGQueryMgr())
	{
		g_GetGQueryMgr()->UnInit();
		g_DelGQueryMgr();
	}

	if (g_GetChatMgr())
	{
		g_GetChatMgr()->UnInit();
		g_DelChatMgr();
	}


	if (g_GetLNotifyMgr())
	{
		g_GetLNotifyMgr()->UnInit();
		g_DelLNotifyMgr();
	}


	//该管理器放在最后回收 管理游戏中所有生物和部件内存的分配
	if (g_GetCreatureMgr())
	{
		g_GetCreatureMgr()->UnInit();
		g_DelCreatureMgr();
	}

	//CreatureMgr内存回收依赖该模块
	if (g_GetBehaviacAIMgr())
	{
		g_GetBehaviacAIMgr()->UnInit();
		g_DelBehaviacAIMgr();
	}

	//任务在管理器CreatureMgr之后 因为PlayerMgr在回收任务部件时需要调用MissionManager管理器
	if (g_GetMissionManager())
	{
		g_GetMissionManager()->UnInit();
		g_DelMissionManager();
	}

	if (g_GetAdventureMgr())
	{
		g_GetAdventureMgr()->UnInit();
		g_DelAdventureMgr();
	}

	//物品管理放在最后（物品都是被其他模块引用）
	if (g_GetItemUseMgr())
	{
		g_GetItemUseMgr()->UnInit();
		g_DelItemUseMgr();
	}

	if (g_GetPlaneMgr())
	{
		g_GetPlaneMgr()->UnInit();
		g_DelPlaneMgr();
	}

	if (g_GetPayLogicMgr())
	{
		g_GetPayLogicMgr()->UnInit();
		g_DelPayLogicMgr();
	}

	if (g_GetSkillMgr())
	{
		g_GetSkillMgr()->Unit();
		g_DelSkillMgr();
	}


	CloseServerConnection(m_net, &m_dbproxyServer);
	CloseServerConnection(m_net, &m_logServer);
	for (auto iter = m_gateConnectMap.begin(); iter != m_gateConnectMap.end(); iter++)
		CloseServerConnection(m_net, &iter->second);
	
	MMO_DELETE(m_pMessageDispatch);

	m_net = NULL;
}

bool LogicService::Update(uint64_t tick)
{
	bool result = false;

	BEGIN_PROFILE("LogicService::_ProcessConnection");
	_ProcessConnection();
	END_PROFILE();

	BEGIN_PROFILE("LogicService::_SyncServiceState");
	_SyncServiceState();
	END_PROFILE();

	BEGIN_PROFILE("LogicService::_CheckDayChange");
	_CheckDayChange();
	END_PROFILE();

	BEGIN_PROFILE("LogicService::SendErrLog");
	if (ServerTime::CheckPerSecs(120)) 
	{
		SendErr(m_logServer.session, EMODULE_ID_SERV_SYS, SERVER_ERR_LOG_COLLECT);
	}
	END_PROFILE();

	////打印技能当前内存大小
	//if (ServerTime::CheckPerFrames(300))
	//	g_GetSkillMgr()->PrintMem();

	BEGIN_PROFILE("ScriptMgr::Update");
	g_GetScriptMgr()->Update(tick);
	END_PROFILE();

	//生物管理器生update
	BEGIN_PROFILE("CreatureMgr::Update");
	//if (IsConnectCenter())
	g_GetCreatureMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("SceneMgr::Update");
	//if (IsConnectCenter())
	g_GetSceneMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("MonsterRefMgr::Update");
	g_GetGeneralCreatureRefMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("MonsterMgr::Update");
	g_GetMonsterMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("ObjectMgr::Update");
	g_GetObjectMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("BehaviacAIMgr::Update");
	g_GetBehaviacAIMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("ActivityMgr::Update");
	g_GetGActivityMgr()->Update(tick);
	END_PROFILE();

	if (IsQuitting())
	{
		goto Exit0;
	}

	result = true;
Exit0:
	BEGIN_PROFILE("_CheckLuaStackLeak");
	_CheckLuaStackLeak();
	END_PROFILE();

	return result;
}

bool LogicService::_ProcessConnection() 
{
	time_t timeInSecond = Time::Now().UnixSec();
	ConnectService(m_net, &m_dbproxyServer, timeInSecond, LogicService::_OnConnectDBProxy, &m_dbproxyServer);
	ConnectService(m_net, &m_centerServer, timeInSecond, LogicService::_OnConnectCenterServer, &m_centerServer);
	ConnectService(m_net, &m_logServer, timeInSecond, LogicService::_OnConnectLogServer, &m_logServer);

	//gate
	CONNECT_MAP::iterator iter = m_gateConnectMap.begin();
	for (; iter != m_gateConnectMap.end(); iter++)
		ConnectService(m_net, &iter->second, timeInSecond, LogicService::_OnConnectGateServer, &iter->second);

	return true;
}

bool LogicService::_OnConnectDBProxy(ISession* session, void* context, bool success)
{
	PROFILE_SEGMENT("LogicService::_OnConnectDBProxy");

	bool result = false;
	SESSION_USER_DATA userdata;
	LogicService* service = g_GetLogicService();
	ServiceConnect* serviceConnect = NULL;

	MMOLOG_ASSERT_EXIT(context != NULL);
	serviceConnect = (ServiceConnect*)context;
	if (success) 
	{
		MMOLOG_ASSERT_EXIT(session != NULL);
		serviceConnect->session = session;
		serviceConnect->connectState = CONNECT_STATE_CONNECTED;
		serviceConnect->serviceType = DBPROXY_SERVER;
		serviceConnect->session->SetUserReq((void*)(LogicService::_OnCloseServer), context);
		serviceConnect->session->SetNetPackHandle((void*)(service->GetServiceMessageDispatch()));
		LogInfoFmtPrint("[logic] connect dbproxy(id:%u, ip:%s:%d) success",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);

		session->SetUserData(userdata);
		service->_SetConnectFlag(CONNECT_DBPROXY_SERVER, true);
		session->SetMark(DBPROXY_SERVER);
	}
	else 
	{
		LogErrFmtPrint("[logic] connect dbproxy(id:%u, ip:%s:%d) fail",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);
		serviceConnect->connectState = CONNECT_STATE_READY;
	}

	result = true;
Exit0:
	return result;
}

bool LogicService::_OnConnectLogServer(ISession* session, void* context, bool success) 
{
	PROFILE_SEGMENT("LogicService::_OnConnectLogServer");

	bool result = false;
	SESSION_USER_DATA userdata;
	LogicService* service = g_GetLogicService();
	ServiceConnect* serviceConnect = NULL;

	MMOLOG_ASSERT_EXIT(context != NULL);
	serviceConnect = (ServiceConnect *)context;
	if (success) 
	{
		MMOLOG_ASSERT_EXIT(session != NULL);
		serviceConnect->session = session;
		serviceConnect->connectState = CONNECT_STATE_CONNECTED;
		serviceConnect->serviceType = LOG_SERVER;
		serviceConnect->session->SetUserReq((void*)(LogicService::_OnCloseServer), context);
		//serviceConnect->session->SetNetPackHandle((void*)(&service->m_serverHandle));
		serviceConnect->session->SetNetPackHandle((void*)(service->GetServiceMessageDispatch()));
		LogInfoFmtPrint("[logic] connect log server(id:%u, ip:%s:%d) success",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);

		userdata.v32 = serviceConnect->id;
		session->SetUserData(userdata);
		service->_SetConnectFlag(CONNECT_LOG_SERVER, true);
		session->SetMark(LOG_SERVER);
	}
	else 
	{
		LogErrFmtPrint("[logic] connect log server(id:%u, ip:%s:%d) fail",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);
		serviceConnect->connectState = CONNECT_STATE_READY;
	}
	result = true;
Exit0:
	return result;
}

bool LogicService::_OnConnectGateServer(ISession* session, void* context, bool success)
{
	PROFILE_SEGMENT("LogicService::_OnConnectGateServer");

	bool result = false;
	SESSION_USER_DATA userdata;
	ServiceConnect* serviceConnect = NULL;

	MMOLOG_ASSERT_EXIT(context != NULL);
	serviceConnect = (ServiceConnect*)context;

	if (success) 
	{
		MMOLOG_ASSERT_EXIT(session != NULL);
		serviceConnect->session = session;
		serviceConnect->connectState = CONNECT_STATE_CONNECTED;
		serviceConnect->serviceType = GATE_SERVER;
		serviceConnect->session->SetUserReq((void*)(LogicService::_OnCloseServer), context);
		serviceConnect->session->SetNetPackHandle((void*)(g_GetLogicService()->GetServiceMessageDispatch()));
		LogInfoFmtPrint("[logic] connect gate server(id:%u, ip:%s:%d) success",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);

		userdata.v32 = serviceConnect->id;
		session->SetUserData(userdata);
		session->SetMark(GATE_SERVER);

		g_GetLogicService()->_Register2Gate(session);
	}
	else 
	{
		LogErrFmtPrint("[logic] connect gate server(id:%u, ip:%s:%d) fail",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);
		serviceConnect->connectState = CONNECT_STATE_READY;
	}

	result = true;
Exit0:
	return result;
}

bool LogicService::_OnConnectCenterServer(ISession* session, void* context, bool success) 
{
	PROFILE_SEGMENT("LogicService::_OnConnectCenter");

	bool result = false;
	SESSION_USER_DATA userdata;
	LogicService*      service = g_GetLogicService();
	ServiceConnect*    serviceConnect = NULL;

	MMOLOG_ASSERT_EXIT(context != NULL);
	serviceConnect = (ServiceConnect*)context;

	if (success) 
	{
		MMOLOG_ASSERT_EXIT(session != NULL);
		serviceConnect->session = session;
		serviceConnect->connectState = CONNECT_STATE_CONNECTED;
		serviceConnect->serviceType = CENTER_SERVER;
		serviceConnect->session->SetUserReq((void*)(LogicService::_OnCloseServer), context);
		serviceConnect->session->SetNetPackHandle((void*)(service->GetServiceMessageDispatch()));
		LogInfoFmtPrint("[logic] connect center server (id:%u, ip:%s:%d) success",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);

		session->SetUserData(userdata);
		service->_SetConnectFlag(CONNECT_CENTER_SERVER, true);
		session->SetMark(CENTER_SERVER);
		service->_Register2Center();
	}
	else {
		LogInfoFmtPrint("[logic] connect center (id:%u, ip:%s:%d) fail",
			serviceConnect->id,
			serviceConnect->remoteIp,
			serviceConnect->remotePort);
		serviceConnect->connectState = CONNECT_STATE_READY;
	}

	result = true;
Exit0:
	return result;
}

void LogicService::_SetConnectFlag(ServiceConnectFlag flag, bool open) 
{
	if (open) 
	{
		m_connectFlag |= flag;
	}
	else 
	{
		m_connectFlag &= ~flag;
	}
	m_syncStateTick = 0;
}

bool LogicService::_SyncServiceState() 
{
	uint64_t tick = Time::Tick();

	if (ServerTime::CheckPerFrames(10)) 
	{
		_SyncServerLoad(false);
	}

	if (tick < m_syncStateTick + SERVER_PING_INTERVAL * 1000)
		return true;

	_SyncServerLoad(true);

	if (m_dbproxyServer.connectState == CONNECT_STATE_CONNECTED)
	{
		SendData(m_dbproxyServer.session, EMODULE_ID_SERV_SYS, DBPROXY_PROTOCOL_PING_REQ);
	}
	if (m_logServer.connectState == CONNECT_STATE_CONNECTED) 
	{
		SendData(m_logServer.session, EMODULE_ID_SERV_SYS, LOG_SERVER_PROTOCOL_PING);
	}
	if (m_centerServer.connectState == CONNECT_STATE_CONNECTED)
	{
		SendData(m_centerServer.session, EMODULE_ID_SERV_SYS, CENTER_SERVER_PROTOCOL_PING);
	}

	if (m_gateConnectMap.empty())
		LogErrFmtPrint("[logic] gate connects empty, it's unnormal...");

	CONNECT_MAP::iterator iter = m_gateConnectMap.begin();
	for (; iter != m_gateConnectMap.end(); iter++)
	{
		if (iter->second.connectState == CONNECT_STATE_CONNECTED)
			SendData(iter->second.session, EMODULE_ID_SERV_SYS, GATE_SERVER_PROTOCOL_PING);
	}

	m_syncStateTick = tick;
	return true;
}

bool LogicService::_SyncServerLoad(bool force) 
{
// to center server
	return true;
}

bool LogicService::_CheckDayChange() 
{
	/*if (IsQuitting()) 
	{
		return false;
	}

	bool isDayChange = false;
	bool isWeekChange = false;

	uint64_t unixSec = ServerTime::UnixSec();
	isDayChange = TimeUtility::CheckDayChange(unixSec, m_lastDayChangeTime, &isWeekChange);
	if (!isDayChange) 
	{
		return false;
	}
	LogDebugFmtPrint("[logic] LogicService::_CheckDayChange daychange=%d, weekchange=%d, lasttime=%u, curtime=%u",
					isDayChange,
					isWeekChange,
					m_lastDayChangeTime,
					unixSec);

	m_lastDayChangeTime = unixSec;

	_OnDayChange();

	if (!isWeekChange)
	{
		return false;
	}*/

	return true;
}

void LogicService::DailyUpdate(uint64_t unixSec)
{
	LogInfoFmtPrint("[logic] LogicService::DailyUpdate...zid:%d, id:%d , unixSec:%lu ", m_zid, m_id, unixSec);
	g_GetCreatureMgr()->DailyUpdate(unixSec);
}

void LogicService::WeekUpdate(uint64_t unixSec)
{
	LogInfoFmtPrint("[logic] LogicService::WeekUpdate...zid:%d, id:%d , unixSec:%lu ", m_zid, m_id, unixSec);
	//
	g_GetCreatureMgr()->WeekUpdate(unixSec);
}

void LogicService::WeekZeroUpdate(uint64_t unixSec)
{
	LogInfoFmtPrint("[logic] LogicService::WeekZeroUpdate...zid:%d, id:%d , unixSec:%lu ", m_zid, m_id, unixSec);
	//计算从开服到现在多少周
	_CalcWeekCountFromOpen(unixSec);
	//
	g_GetCreatureMgr()->WeekZeroUpdate(unixSec);
}

void LogicService::DailyZeroUpdate(uint64_t unixSec)
{
	LogInfoFmtPrint("[logic] LogicService::DailyZeroUpdate...zid:%d, id:%d , unixSec:%lu ", m_zid, m_id, unixSec);
	g_GetCreatureMgr()->DailyZeroUpdate(unixSec);
}

void LogicService::_OnDayChange()
{}

bool LogicService::_CheckLuaStackLeak() 
{
	LuaScript* sc = g_GetScriptMgr()->GetScript();
	if (sc == nullptr) 
	{
		return false;
	}

	int topIndex = sc->GetTopIndex();
	if (topIndex == 0) 
	{
		return true;
	}

	LogErrFmtPrint("[logic] script stack leak (%d)!", topIndex);
	sc->SetTopIndex(0);

	return false;
}

void LogicService::_CalcWeekCountFromOpen(uint64_t curTime)
{
	//计算开服那一周还剩余的时间
	Date curDate = Time::GetLocalDate(m_openTime);
	uint32_t wday = (curDate.wday == 0) ? 7 : curDate.wday;
	uint64_t openDaySec = curDate.hour * 3600 + curDate.min * 60 + curDate.sec;
	uint64_t weekLefSec = (7 - wday) * 24 * 3600 + (24 * 3600 - openDaySec);
	
	m_weekCountFromOpen = 1; 
	if (curTime >= (m_openTime + weekLefSec))
	{
		uint64_t interSec = curTime - (m_openTime + weekLefSec);
		uint32_t weekCount = 0;
		uint64_t weekSec = 24 * 3600 * 7;
		weekCount = interSec / weekSec;
		if (0 != (interSec % weekSec))
		{
			weekCount += 1;
		}
		m_weekCountFromOpen += weekCount;
	}

	/* 测试时间代码，如果发现有问题，可以打开注释 测试
	
	uint64_t testlast = 1510588799;
	uint64_t testcur = 1510588800;
	uint64_t testcur1 = 1510588800 + 5 * 3600;
	uint64_t testcur2 = 1510588800 + 5 * 3600 * 24;

	uint64_t testlastweek = 1510502399;
	uint64_t testcurweek = 1510502400;
	uint64_t testcurweek1 = 1510502400 + 5 * 3600;
	uint64_t testcurweek2 = 1510502400 + 10 * 3600 * 24;

	bool ret = TimeUtility::CheckDayUpdate(testcur, testlast);
	bool ret1 = TimeUtility::CheckDayUpdate(testcur1, testlast);
	bool ret2 = TimeUtility::CheckDayUpdate(testcur2, testlast);

	bool ret3 = TimeUtility::CheckWeekUpdate(testcurweek, testlastweek);
	bool ret4 = TimeUtility::CheckWeekUpdate(testcurweek1, testlastweek);
	bool ret5 = TimeUtility::CheckWeekUpdate(testcurweek2, testlastweek);*/

	LogInfoFmtPrint("[logic] LogicService::_CalcWeekCountFromOpen....zid:%d, id:%d, m_weekCountFromOpen:%u, curTime:%lu, opentime:%lu ", m_zid, m_id, m_weekCountFromOpen, curTime, m_openTime);
}

// 本函数内所调用的各个子模块存盘函数需支持重入，避免某个模块的一次失败导致后续模块无法完成存盘
// 函数返回false，将会继续尝试调用直到返回true
// 与CenterServer一致
bool LogicService::Quit() 
{
	bool result = false;
//	bool retCode = false;
	static bool callScriptClose = false;

	LuaScript* sc = g_GetScriptMgr()->GetScript();

	MMOLOG_PROCESS_ERROR(IsRuning());
	//if (m_listenHandle != nullptr) 

	//if (m_gateServer.session != nullptr)
	//{

		// 面向客户端的连接，会先关闭监听防止新的用户连上来。面向服务端的不关端口，退出期间服务器之间还有数据要同步
		//m_net->CloseListen(m_listenHandle);
		//m_listenHandle = nullptr;
		//m_net->Close(m_gateServer.session);

	//}


	if (!callScriptClose && sc != nullptr) 
	{
		callScriptClose = true;
		//@temp by JinnMa
//		sc->CallTableFuncVoid("LSEvent", "OnClose");
	}

	//retCode = g_GetAccessMgr()->ExitAllEnterAccount();
	//MMOLOG_PROCESS_ERROR(retCode);
	
//	retCode = g_GetPlayerMgr()->ExitAllFamily();
//	MMOLOG_PROCESS_ERROR(retCode);

	SetRuningStatus(STATUS_QUITTING);


	//先保存该服务器上玩家数据
	g_GetCreatureMgr()->SaveAllPlayer();


	result = true;
Exit0:
	return result;
}

IMessageDispatch *LogicService::GetServiceMessageDispatch()
{
	return m_pMessageDispatch;
}

bool LogicService::HandleConsoleCmd(const char* cmd)
{
	// 创建角色
	if (stricmp(cmd, "create character") == 0)
	{
		CreateCharacterRequest reqPack;
		reqPack.set_requestid(100);
		reqPack.set_groupid(1);
		reqPack.set_name("cg_name");
		CharacterDBInfo* charInfo = reqPack.mutable_charinfo();
		charInfo->set_charid(100000);
		charInfo->set_groupid(1);
		CharacterDBBaseInfo* charBaseInfo = charInfo->mutable_basedata();
		//charBaseInfo->set_channelid("cg_channel");
		//charBaseInfo->set_userid("cg_userid");
		//charBaseInfo->set_username("cg_name");
		charBaseInfo->set_createtime(ServerTime::Tick());
		charBaseInfo->set_lastsavetime(0);
		charBaseInfo->set_onlinetime(0);
		charBaseInfo->set_logintime(0);
		charBaseInfo->set_logouttime(0);
		ValueCurrency* currency = charBaseInfo->add_currency();
		currency->set_cointype(1);
		currency->set_coinvalue(1);
		charBaseInfo->set_name("cg_name");
		charBaseInfo->set_sex(1);
		charBaseInfo->set_prof(1);
		charBaseInfo->set_level(1);
		charBaseInfo->set_exp(1);
		charBaseInfo->set_hp(100);
		charBaseInfo->set_fightpower(100);
		charBaseInfo->set_enter_scene_id(1010);
		charBaseInfo->set_enterposx(0);
		charBaseInfo->set_enterposy(0);

		SendDataToDBProxy(EMODULE_ID_PLANE, DBPROXY_PROTOCOL_CREATE_CHARACTER_REQ, &reqPack);
	}
	else if (stricmp(cmd, "set character") == 0)
	{
	}
	else if (stricmp(cmd, "get character") == 0)
	{ 
	}
	else if (stricmp(cmd, "get character list") == 0)
	{
	}

	return (cmd[0] != '\0');
}

bool LogicService::SendDataToDBProxy(const char* buf, uint32_t length) 
{
	bool result = false;
	bool retCode = false;
	retCode = SendDataEx(m_dbproxyServer.session, buf, length);
	MMOLOG_PROCESS_ERROR(retCode);

	result = true;
Exit0:
	return result;
}

bool LogicService::SendDataToDBProxy(uint16_t module, uint16_t protocolCmd, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;
	retCode = SendDataEx(m_dbproxyServer.session,module, protocolCmd, buf);
	MMOLOG_PROCESS_ERROR(retCode);

	result = true;
Exit0:
	return result;
}

bool LogicService::SendCmdToDBProxy(uint32_t protocolCmd) 
{
	bool result = false;
	bool retCode = false;
	retCode = SendData(m_dbproxyServer.session, protocolCmd);
	MMOLOG_PROCESS_ERROR(retCode);

	result = true;
Exit0:
	return result;
}

bool LogicService::IsConnectDBProxy() 
{
	return m_dbproxyServer.session != nullptr;
}

bool LogicService::SendDataToCenter(uint16_t module, uint16_t protocolCmd, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;

	MMOLOG_PROCESS_ERROR(m_centerServer.session != nullptr);
	retCode = SendData(m_centerServer.session, module, protocolCmd, buf);
	MMO_PROCESS_ERROR(retCode);

	result = true;
Exit0:
	return result;
}

bool LogicService::IsConnectCenter()
{
	return m_centerServer.session != nullptr;
}

bool LogicService::SendDataToClient(uint64_t cid, uint16_t module, uint16_t command, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;

	ServiceConnect* gateCon = nullptr;
	char* retbuf = nullptr;
	uint32_t length = 0;

	uint32_t clientId = 0;
	uint32_t gateId = 0;

	g_GetCreatureMgr()->GetGateClientId(cid, gateId, clientId);
	MMOLOG_PROCESS_ERROR(gateId > 0);
	MMOLOG_PROCESS_ERROR(clientId > 0);

	gateCon = GetGateConnect(gateId);
	MMOLOG_PROCESS_ERROR(gateCon != nullptr);
	MMOLOG_PROCESS_ERROR(gateCon->session != NULL);

	retCode = PackDataWithPreData(module, command, buf, &retbuf, &length, &clientId);
	MMO_PROCESS_ERROR(retCode);

	retCode = m_net->Send(gateCon->session, retbuf, length);
	MMO_PROCESS_ERROR(retCode);

	result = true;
Exit0:
	return result;
}

bool LogicService::SendDataToClient(SET_UINT64 &setCharID, uint16_t module, uint16_t command, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;

	char* packBuf = nullptr;
	char* finalPackBuf = nullptr;

	uint32_t length = 0;
	MAP_UINT32_LST_UINT32 gateClientsMap;
	MAP_UINT32_LST_UINT32::iterator iter;
	ServiceConnect* gateConn = nullptr;

	MMOLOG_ASSERT_EXIT(m_net != NULL);
	MMOLOG_PROCESS_ERROR(buf != NULL);

	MMOLOG_PROCESS_ERROR(!setCharID.empty());

	g_GetCreatureMgr()->GetGateClientIds(gateClientsMap, setCharID);
	MMOLOG_PROCESS_ERROR(!gateClientsMap.empty());

	//先打一个内容包，再根据不同玩家在不同网关分别填前置数据包,这样服务器不用每次都打包内容包
	retCode = PackData(module, command, buf, &packBuf, &length);
	MMOLOG_PROCESS_ERROR(retCode);

	for (iter = gateClientsMap.begin(); iter != gateClientsMap.end(); iter++)
	{
		//填前置数据，必须要先调用PackData
		RepackWithPreData(&finalPackBuf, length, iter->second);

		gateConn = GetGateConnect(iter->first);
		if (gateConn == nullptr)
		{
			LogErrFmtPrint("logic cannt send data to gate, gate connect == null, gateId:%d, cmd:%d", iter->first, command);
			continue;
		}
		if (gateConn->session == nullptr)
		{
			LogErrFmtPrint("logic cannt send data to gate, gate session == null, gateId:%d, cmd:%d", iter->first, command);
			continue;
		}

		retCode = m_net->Send(gateConn->session, finalPackBuf, length);
		if (!retCode)
			LogErrFmtPrint("logic cannt send data to gate, gateId:%d, cmd:%d", iter->first, command);

		packBuf = nullptr;
		length  = 0;
	}

	result = true;
Exit0:
	return result;
}

bool LogicService::SendDataToAllClient(uint16_t module, uint16_t command, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;
	char* packBuf = nullptr;
	uint32_t length = 0;

	MMOLOG_ASSERT_EXIT(m_net != NULL);
	MMOLOG_PROCESS_ERROR(buf != NULL);

	retCode = PackDataWithPreData(module,command, buf, &packBuf, &length);
	MMO_PROCESS_ERROR(retCode);

	for (CONNECT_MAP::iterator iter = m_gateConnectMap.begin(); iter != m_gateConnectMap.end(); iter++)
	{
		if (iter->second.session == nullptr)
		{
			LogErrFmtPrint("logic SendDataToAllClient, gate session == null, gateId:%d, cmd:%d", iter->first, command);
			continue;
		}
		retCode = m_net->Send(iter->second.session, packBuf, length);
		if (!retCode)
			LogErrFmtPrint("logic SendDataToAllClient, send data to gate err, gateId:%d, cmd:%d", iter->first, command);
	}

	result = true;
Exit0:
	return result;
}

bool LogicService::SendDataToClient(MAP_UINT32_LST_UINT32& gateClientsMap, uint16_t module, uint16_t command, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;

	char* packBuf = nullptr;
	char* finalPackBuf = nullptr;

	uint32_t length = 0;
	MAP_UINT32_LST_UINT32::iterator iter;
	ServiceConnect* gateConn = nullptr;

	MMOLOG_ASSERT_EXIT(m_net != NULL);
	MMOLOG_PROCESS_ERROR(buf != NULL);

	//先打一个内容包，再根据不同玩家在不同网关分别填前置数据包,这样服务器不用每次都打包内容包
	retCode = PackData(module, command, buf, &packBuf, &length);
	MMOLOG_PROCESS_ERROR(retCode);

	for (iter = gateClientsMap.begin(); iter != gateClientsMap.end(); iter++)
	{
		//填前置数据，必须要先调用PackData
		RepackWithPreData(&finalPackBuf, length, iter->second);

		gateConn = GetGateConnect(iter->first);
		if (gateConn == nullptr)
		{
			LogErrFmtPrint("logic cannt send data to gate, gate connect == null, gateId:%d, cmd:%d", iter->first, command);
			continue;
		}
		if (gateConn->session == nullptr)
		{
			LogErrFmtPrint("logic cannt send data to gate, gate session == null, gateId:%d, cmd:%d", iter->first, command);
			continue;
		}

		retCode = m_net->Send(gateConn->session, finalPackBuf, length);
		if (!retCode)
			LogErrFmtPrint("logic cannt send data to gate, gateId:%d, cmd:%d", iter->first, command);

		packBuf = nullptr;
		length = 0;
	}

    result = true;
Exit0:
	return result;
}

bool LogicService::SendDataToClient(uint32_t gateId, LIST_UINT32 & clientIds, uint16_t module, uint16_t command, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;

	char* packBuf = nullptr;

	uint32_t length = 0;
	MAP_UINT32_LST_UINT32::iterator iter;
	ServiceConnect* gateConn = nullptr;

	MMOLOG_ASSERT_EXIT(m_net != NULL);
	MMOLOG_PROCESS_ERROR(buf != NULL);

	retCode = PackDataWithPreData(module, command, buf, &packBuf, &length, &clientIds);
	MMOLOG_PROCESS_ERROR(retCode);

	gateConn = GetGateConnect(gateId);
	if (gateConn == nullptr)
	{
		LogErrFmtPrint("logic cannt send data to gate, gate connect == null, gateId:%d, cmd:%d", gateId, command);
		MMOLOG_PROCESS_ERROR(false);
	}
	if (gateConn->session == nullptr)
	{
		LogErrFmtPrint("logic cannt send data to gate, gate session == null, gateId:%d, cmd:%d", gateId, command);
		MMOLOG_PROCESS_ERROR(false);
	}

	retCode = m_net->Send(gateConn->session, packBuf, length);
	MMOLOG_PROCESS_ERROR(retCode);

	packBuf = nullptr;
	length = 0;

    result = true;
Exit0:
	return result;
}

bool LogicService::SendDataToClient(uint32_t gateId, uint32_t clientId, uint16_t module, uint16_t command, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;

	char* packBuf = nullptr;

	uint32_t length = 0;
	ServiceConnect* gateConn = nullptr;

	MMOLOG_ASSERT_EXIT(m_net != NULL);
	MMOLOG_PROCESS_ERROR(buf != NULL);

	retCode = PackDataWithPreData(module, command, buf, &packBuf, &length, &clientId);
	MMOLOG_PROCESS_ERROR(retCode);

	gateConn = GetGateConnect(gateId);
	if (gateConn == nullptr)
	{
		LogErrFmtPrint("logic cannt send data to gate, gate connect == null, gateId:%d, cmd:%d", gateId, command);
		MMOLOG_PROCESS_ERROR(false);
	}
	if (gateConn->session == nullptr)
	{
		LogErrFmtPrint("logic cannt send data to gate, gate session == null, gateId:%d, cmd:%d", gateId, command);
		MMOLOG_PROCESS_ERROR(false);
	}

	retCode = m_net->Send(gateConn->session, packBuf, length);
	MMOLOG_PROCESS_ERROR(retCode);

	packBuf = nullptr;
	length = 0;

    result = true;
Exit0:
	return result;
}

bool LogicService::SendLogToLogServer(JsonObject& json)
{
	bool result = false;
	bool retCode = false;
	string logstr = json.ToString();
	retCode = SendDataNoProtobuf(SERVER_INTERNAL_LOG, EMODULE_ID_SERV_SYS, m_logServer.session, logstr.c_str(), logstr.size());
	MMOLOG_PROCESS_ERROR(retCode);
	result = true;
Exit0:
	return result;
}

bool LogicService::ResetSessionTimeout(ISession* session, uint32_t timeMsec /*= 0xFFFFFFFF*/) 
{
	MMOLOG_ASSERT(m_net != nullptr);
	MMOLOG_ASSERT(session != nullptr);
	if (m_net != nullptr && session != nullptr) 
	{
		return m_net->ResetTimeout(session, timeMsec);
	}
	return false;
}

uint64_t LogicService::GetDBRequestCount() 
{
	return ++m_dbRequestCount;
}

bool LogicService::_Register2Center()
{
	LogicService*      service = g_GetLogicService();
	LogicCenterRegister centerRegiste;

	LuaParser  parser;
	list<uint32_t> runMapIdsLst;
	list<uint32_t>::iterator iter;
	list<uint32_t>::iterator iterEnd;

	// register server to center server

	bool result = false;
	bool retCode = false;

	if (m_loadAllMapIds)
	{
		retCode = g_GetSceneMgr()->InitRunSceneUseMapConfig(runMapIdsLst);
		MMOLOG_PROCESS_ERROR(retCode);
	}
	else
	{
		if (!parser.OpenFileTry(s_LogicMap_file))
		{
			retCode = parser.OpenFile(s_LogicMap_BackUp_file);
			MMOLOG_ASSERT(retCode);
		}

		char buf[SERVER_NAME];
		snprintf(buf, SERVER_NAME, "Logic%d", m_id);
		LuaRef  table = parser.GetRef(buf);
		MMOLOG_PROCESS_ERROR(table.isTable());
		MMOLOG_PROCESS_ERROR(table.length() > 0);

		uint32_t mapId = 0;
		int count = table.length();
		for (int i = 0; i < count; ++i)
		{
			mapId = table[i + 1].cast<uint32_t>();
			runMapIdsLst.push_back(mapId);
		}
		MMOLOG_PROCESS_ERROR(g_GetSceneMgr()->InitRunSceneInLogic(runMapIdsLst));
	}

	LogInfoFmtPrint("this logic:%u run these maps, ids:\n\t", m_id);
	iter = runMapIdsLst.begin();
	iterEnd = runMapIdsLst.end();
	for (; iter != iterEnd; iter++)
	{
		centerRegiste.add_mapids(*iter);
		LogInfoFmtPrint("mapId:%u", *iter);
	}
	centerRegiste.set_logicid(m_id);
	retCode = service->SendData(m_centerServer.session, EMODULE_ID_SERV_SYS, LOGIC_REGISTE_CENTER, &centerRegiste);
	MMOLOG_PROCESS_ERROR(retCode);

Exit0:
	return result;
}

bool LogicService::_Register2Gate(ISession *pSession)
{
	bool result = false;
	bool retCode = false;
	LogicGateRegister registe;

	registe.set_logicid(m_id);

	retCode = SendData(pSession, EMODULE_ID_SERV_SYS, LOGIC_REGISTE_GATE, &registe);
	MMOLOG_PROCESS_ERROR(retCode);

	result = true;
Exit0:
	return result;
}

ServiceConnect* LogicService::GetGateConnect(uint32_t gateId)
{
	CONNECT_MAP::iterator iter = m_gateConnectMap.find(gateId);
	if (iter != m_gateConnectMap.end())
	{
		return &iter->second;
	}
	return nullptr;
}
